Skip to content

下拉刷新 xPullRefresh


预览

介绍

常用下拉容器,不要虚拟切片。pulldown / refresh 用 Promise,组件自己收 refresher。listType 切换 scroll-view / list-view。#top / #sticky 和内容同一层滚动容器。不要原生子协商。scroll-view:App / Web #sticky 到达后 fixed,小程序 using-sticky。list-view:吸顶与 scroll-view 同一套逻辑,不要 sticky-section,App / Web hold + fixed,小程序 sticky。

平台兼容

HarmonyH5andriodIOS小程序UTSUNIAPP-X SDKversion
☑️☑️☑️☑️4.76+1.1.18

文件路径

ts

@/uni_modules/tmx-ui/components/x-pull-refresh/x-pull-refresh.uvue

使用

ts

<x-pull-refresh></x-pull-refresh>

Props 属性

名称说明类型默认值
height``
string"100%"
full``
booleantrue
empty``
booleanfalse
listType``
string"scroll-view"
refresh``
xPullRefreshFun() : xPullRefreshFun => { return null }
pulldown``
xPullRefreshFun() : xPullRefreshFun => { return null }
showScrollbar``
booleanfalse

Events 事件

名称参数说明
scroll--
refresh--
pulldown--

Slots 插槽

名称说明数据
top--
sticky--
empty--
default--
refresh--

Ref 方法

名称参数返回值说明
refreshSize---
resetScroll---
setScrollTop---

示例文件路径

json

/pages/fankui/pull-refresh

示例源码

uvue
vue
<template>
	<!-- #ifdef MP-WEIXIN -->
	<page-meta :page-style="`background-color:${xThemeConfigBgColor}`">
		<navigation-bar :background-color="xThemeConfigNavBgColor"
			:front-color="xThemeConfigNavFontColor"></navigation-bar>
	</page-meta>
	<!-- #endif -->

	<view class="page">
		<x-pull-refresh class="pageList" height="100%" :list-type="listType" :empty="list.length == 0"
			:pulldown="onPulldown" :refresh="onLoadMore">
			<template #top>
				<x-sheet :margin="[0, 0, 0, 8]">
					<x-text font-size="18" class=" text-weight-b mb-8">下拉刷新 xPullRefresh</x-text>
					<x-text color="#999999" class="mb-12">常用下拉容器。向下先推顶部,菜单吸顶后再滚内容。下拉和触底都交 Promise。listType 可切
						scroll-view / list-view。本页 {{ list.length }} 条,当前 {{ listType }}。</x-text>
					<view class="flex flex-row flex-row-center-between">
						<x-button size="small" class="flex-1" @click="toggleListType">容器</x-button>
						<x-button size="small" class="ml-5 flex-1" @click="reloadAll">重载</x-button>
						<x-button size="small" class="ml-5 flex-1" @click="appendRows">追加</x-button>
						<x-button size="small" class="ml-5 flex-1" @click="clearAll">清空</x-button>
					</view>
				</x-sheet>
			</template>
			<template #sticky="{ pinned }">
				<view >
					<x-tabs v-model="menuId" :list="tabList" item-width="33.333%" height="44"></x-tabs>
				</view>
			</template>

			<template v-if="listType == 'scroll-view'">
				<view style="height: 8px;"></view>
				<view v-for="item in list" :key="item.key" class="cardWrap">
					<view class="card" :style="{ backgroundColor: cardBg }">
						<x-text>{{ item.title }}</x-text>
					</view>
				</view>
			</template>
			<template v-else>
				<list-item>
					<view style="height: 8px;"></view>
				</list-item>
				<list-item v-for="item in list" :key="item.key">
					<view class="cardWrap">
						<view class="card" :style="{ backgroundColor: cardBg }">
							<x-text>{{ item.title }}</x-text>
						</view>
					</view>
				</list-item>
			</template>
			<template #empty>
				<x-empty v-if="list.length == 0" :empty="true" :loading="false" btn-label="加载数据"
					@click="reloadAll"></x-empty>
			</template>
		</x-pull-refresh>
	</view>
</template>

<script lang="ts" setup>
	import { computed, ref } from "vue"
	import { xConfig, TABS_ITEM_INFO } from "@/uni_modules/tmx-ui"

	type DemoRow = {
		key : string
		title : string
	}

	function makeRows(from : number, count : number) : DemoRow[] {
		const out : DemoRow[] = []
		for (let i = 0; i < count; i++) {
			const n = from + i
			out.push({
				key: n.toString(),
				title: "下拉刷新,上拉加载 - " + (n + 1).toString()
			})
		}
		return out
	}

	const listType = ref<string>("scroll-view")
	const menuId = ref<string>("all")
	const tabList = [
		{ id: "all", title: "综合" },
		{ id: "new", title: "新品" },
		{ id: "hot", title: "热门" }
	] as TABS_ITEM_INFO[]
	const list = ref<DemoRow[]>(makeRows(0, 12))

	const cardBg = computed(() : string => {
		if (xConfig.dark == "dark") return xConfig.sheetDarkColor
		return "#ffffff"
	})

	function wait(ms : number) : Promise<void> {
		return new Promise<void>((resolve) => {
			setTimeout(() => {
				resolve()
			}, ms)
		})
	}

	function toggleListType() : void {
		if (listType.value == "list-view") {
			listType.value = "scroll-view"
			return
		}
		listType.value = "list-view"
	}

	function reloadAll() : void {
		list.value = makeRows(0, 8)
	}

	function appendRows() : void {
		list.value = list.value.concat(makeRows(list.value.length, 4))
	}

	function keepEight() : void {
		list.value = list.value.slice(0, 8)
	}

	function clearAll() : void {
		list.value = [] as DemoRow[]
	}

	async function onPulldown() : Promise<void> {
		await wait(800)
		list.value = makeRows(0, 8)
	}

	async function onLoadMore() : Promise<void> {
		await wait(600)
		appendRows()
	}
</script>

<style scoped>
	.page {
		flex: 1;
		display: flex;
		flex-direction: column;
	}

	.pageList {
		flex: 1;
		min-height: 0;
	}


	.cardWrap {
		padding: 0 8px 8px 8px;
	}

	.card {
		height: 120px;
		padding: 16px;
		border-radius: 10px;
		display: flex;
		flex-direction: column;
		justify-content: center;
	}
</style>
最近更新